Skip to main content

Configuring with Ansible

Ansible installs and configures the software running inside each server — Docker, application stacks, CI runners, monitoring agents — after Terraform has provisioned the underlying VM (see Provisioning with Terraform).

Inventory and access

ansible/hetzner-main/inventory.ini groups the Proxmox VMs by role (builders, synthesis_test, webserver, observability, api_gateway, services_user, services_staff), referencing the SSH aliases set up in Getting Started rather than literal IPs — ansible.cfg sets a fixed remote user (ansible-control) and disables host-key checking, relying on the ProxyJump config instead. Amergin and Puca have their own separate inventories under ansible/amergin/ and ansible/puca/, since neither is reached through the same jump host.

The pattern common to every VM

Nearly every playbook follows the same shape:

  1. Install Docker CE from Docker's official apt repo, and configure /etc/docker/daemon.json with an insecure-registry entry for 10.0.0.2:5000 (the legacy services VM, which hosts the shared internal registry).
  2. Create a dedicated deploy user, authorized with the CI runner's SSH public key, so GitHub Actions / Gitea Actions workflows can ssh in directly and run docker compose pull && up -d — rather than embedding registry or server credentials in CI secrets.
  3. Run Grafana Alloy as a standalone container (outside any app's own Compose stack), shipping logs and metrics to the observability VM. What gets tailed differs per VM — a specific log file, the Docker socket for container discovery, or an nginx access log.
  4. Configure UFW: allow SSH, allow the webserver VM as the reverse-proxy ingress, deny everything else inbound by default.

Tags

Playbooks are tagged so a single run can do exactly as much as intended:

  • setup — full first-time bring-up of a VM (installs everything).
  • update — safe to re-run against a live VM; re-applies idempotent configuration without disruptive steps.
  • apps — redeploys only the application Compose stacks (pull + up), without touching base VM configuration. Used by make deploy-services-user-apps / make deploy-services-staff-apps.
  • Stack-specific tags for stateful apps that shouldn't be bundled with the stateless apps tag — e.g. gitea, rocketchat on services-staff, or gitea-runner on docker-build.

See Common Operations for the full list of Make targets that wrap these tags.